using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

using StateMachine_Graphical_Editor.Shapes;
using StateMachine_Graphical_Editor.Utils;
using StateMachine_Graphical_Editor.Utils.Forms_RunTime_Managment;
using StateMachine_Graphical_Editor.Graphics_Rendering;


namespace StateMachine_Graphical_Editor.Forms
{
    /// <summary>
    /// Create a guard statement for a transition
    /// </summary>
    public partial class AddGuardForm : Form
    {
        #region Members:

        string guardStatement = "";

        #region Constatnts:

        private const String AND_OPERATOR = "&&";
        private const String OR_OPERATOR = "||";
        private const String EQUAL_OPERATOR = "=";
        private const String NOT_EQUAL_OPERATOR = "!=";

        #endregion

        #endregion

        #region C'tors:

        public AddGuardForm()
        {
            InitializeComponent();
        }
        public AddGuardForm(string oldGuard)
            : this()
        {
            if (! string.IsNullOrEmpty(oldGuard))
                guardStatement = oldGuard;
        }

        #endregion

        #region Propertis:

        public string GuardStatement
        {
            get { return guardStatement; }
            set { guardStatement = value; this.GuardTextBox.Text = value; }//TODO parse it to text box!!
        }

        #endregion

        #region Event handlers:

        private void Submitbutton_Click(object sender, EventArgs e)
        {
            String normalizedGuardStatement = normalizeGuard(GuardTextBox.Text);
            
            if (isGuardLegal(normalizedGuardStatement))
            {
                guardStatement = normalizedGuardStatement;
            }
            else
            {
                MessageBox.Show(
                        this,
                        "Error in " + GuardTextBox.Text +"\nConstruct a guard statement as instructed above",
                        "Error in phrase",
                        MessageBoxButtons.OK);
                return;
            }

            this.Close();
        }

        private void cancelButton_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        #endregion

        #region Helpers:

        /// <summary>
        /// Check for basic legality conditions about the guard statement entered:
        /// <para>Order of brackets</para>
        /// <para>Structure of equality expressions</para>
        /// </summary>
        /// <param name="normalizedGuardStatement">The staement to parse</param>
        /// <returns>true if legal string, false if not</returns>
        private bool isGuardLegal(String normalizedGuardStatement)
        {
            //check brackets
            char[] checkBrackets = normalizedGuardStatement.ToCharArray();
            int bracketCounter = 0;
            for (int i = 0; i < checkBrackets.Length; i++)
            {
                if (checkBrackets[i].Equals('('))
                    bracketCounter++;
                if (checkBrackets[i].Equals(')'))
                    bracketCounter--;
            }
            if (bracketCounter != 0)
                return false;

            //check valid literal expression
            String[] GuardTypes = normalizedGuardStatement.Split(new char[] { '(', ')' }, StringSplitOptions.RemoveEmptyEntries);
            foreach (String statement in GuardTypes)
            {
                statement.Trim();
                if (String.IsNullOrEmpty(statement))
                    continue;

                String[] expressions = 
                    statement.Split(
                        new String[] { "&&", "||" }, 
                        StringSplitOptions.None);

                //elements of the shape: X=8 or X!=8
                foreach (String expression in expressions)
                {
                    expression.Trim();
                    if (String.IsNullOrEmpty(expression))
                        return false;

                    String[] literals =
                        expression.Split(
                            new String[] { "!=", "=" },
                            StringSplitOptions.RemoveEmptyEntries);

                    if (literals.Length != 2) //must be literal and value
                        return false;
                }
            }
            return true;
        }

        /// <summary>
        /// remove spaces from string
        /// </summary>
        /// <param name="guardStatement"></param>
        /// <returns></returns>
        private String normalizeGuard(String guardStatement)
        {
            return guardStatement.Replace(" ", "");
        }

        #endregion
    }
}